#include "Graphic.h"
#include <assert.h>

D3DXGraphic* D3DXGraphic::_d3dxInstance = 0;

D3DXGraphic* D3DXGraphic::GetInstance()
{
	if (_d3dxInstance == NULL)
		_d3dxInstance = new D3DXGraphic;

	return _d3dxInstance;
}

D3DXGraphic::D3DXGraphic()
{
	pDevice = NULL;
	pDirect3D = NULL;
	pBackBuffer = NULL;
}

bool D3DXGraphic::InitWindow(HINSTANCE hInstance, HWND& hWnd)
{
	WNDCLASSEX wc;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.hInstance = hInstance;

	wc.lpfnWndProc = (WNDPROC)D3DXGraphic::WinProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hIcon = NULL;
	wc.hIconSm = NULL;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = APP_NAME;
	//register a window class
	RegisterClassEx(&wc);

	hWnd = CreateWindow(
		APP_NAME,
		"Game Begin",
		WS_OVERLAPPEDWINDOW,
		300,
		50,
		SCREEEN_WIDTH,
		SCREEN_HEIGHT,
		NULL,
		NULL,
		hInstance,
		NULL);
	if (!hWnd)
		return NULL;

	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);
	return true;
}

bool D3DXGraphic::InitDirectX(HWND hWnd)
{
	pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
	D3DPRESENT_PARAMETERS d3dpp;

	ZeroMemory(&d3dpp, sizeof(d3dpp));

	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
	d3dpp.BackBufferCount = 1;
	d3dpp.BackBufferHeight = SCREEN_HEIGHT;
	d3dpp.BackBufferWidth = SCREEEN_WIDTH;

	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
	d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

	HRESULT result;
	result = pDirect3D->CreateDevice(
		D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp,
		&pDevice);
	assert(!FAILED(result));
	//Lay con tro bo nho dem backbuffer
	result = pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
	assert(!FAILED(result));

	return true;
}

void D3DXGraphic::BeginFrame(LPDIRECT3DSURFACE9 backGround, D3DCOLOR fillColor)
{
	pDevice->Clear(0, NULL, D3DCLEAR_TARGET, fillColor, 0.0f, 0);
	pDevice->BeginScene();
	pDevice->StretchRect(
		backGround,
		NULL,
		pBackBuffer,
		NULL,
		D3DTEXF_NONE);
}


void D3DXGraphic::EndFrame()
{
	pDevice->EndScene();
	pDevice->Present(NULL, NULL, NULL, NULL);
}

D3DXGraphic::~D3DXGraphic()
{
	if (pDirect3D)
		pDirect3D->Release();

	if (pDevice)
		pDevice->Release();

	if (pBackBuffer)
		pBackBuffer->Release();
}

LPDIRECT3DSURFACE9 D3DXGraphic::CreateSurfaceFromFile(LPSTR FilePath)
{
	D3DXIMAGE_INFO info;

	HRESULT result = D3DXGetImageInfoFromFile(FilePath, &info);
	if (result != D3D_OK)
	{
		return NULL;
	}

	LPDIRECT3DSURFACE9 surface;

	pDevice->CreateOffscreenPlainSurface(
		info.Width,				// width
		info.Height,			// height
		D3DFMT_X8R8G8B8,		// format
		D3DPOOL_DEFAULT,
		&surface,
		NULL);

	result = D3DXLoadSurfaceFromFile(
		surface, 		// surface
		NULL,			// destination palette	
		NULL,			// destination rectangle 
		FilePath,
		NULL,			// source rectangle
		D3DX_DEFAULT, 	// filter image
		D3DCOLOR_XRGB(0, 0, 0),				// transparency (0 = none)
		NULL);			// reserved

	if (result != D3D_OK)
	{
		return NULL;
	}

	return surface;
}
LPDIRECT3DSURFACE9 D3DXGraphic::LoadSurface(char *filePath)
{
	LPDIRECT3DSURFACE9 image = NULL;
	D3DXIMAGE_INFO info;
	HRESULT result;
	result = D3DXGetImageInfoFromFile(filePath, &info);
	if (result != D3D_OK)
		return NULL;
	result = pDevice->CreateOffscreenPlainSurface(info.Width,
		info.Width,
		D3DFMT_X8R8G8B8,
		D3DPOOL_DEFAULT,
		&image,
		NULL);
	if (result != D3D_OK)
		return NULL;
	result = D3DXLoadSurfaceFromFile(
		image,
		NULL,
		NULL,
		filePath,
		NULL,
		D3DX_DEFAULT,
		0,
		NULL);
	if (result != D3D_OK)
		return NULL;
	return image;
}

LRESULT CALLBACK D3DXGraphic::WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
